<?php

namespace App\Http\Controllers\Backend;

use App\Repository\Models\Action;
use App\Repository\Models\ActionPermission;
use App\Repository\Models\MenuPermission;
use App\Repository\Models\PermissionRole;
use App\Repository\Models\Permission;

use App\Repository\Repositories\Interfaces\MenuRepository;
use App\Repository\Repositories\Interfaces\ActionRepository;
use App\Repository\Repositories\Interfaces\PermissionRepository;
use App\Repository\Repositories\Interfaces\MenuPermissionRepository;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
use Illuminate\Support\Facades\DB;

class MenuController extends BaseController
{
    private $menuPermission;
    private $menuRepository;
    private $ActionRepository;
    private $request;
    private $permissionRepository;


    public function __construct(MenuRepository $menuRepository,Request $request,ActionRepository $ActionRepository, PermissionRepository $permissionRepository,MenuPermissionRepository $menuPermission)
    {
        parent::__construct();
        $this->menuPermission = $menuPermission;
        $this->permissionRepository = $permissionRepository;
        $this->menuRepository = $menuRepository;
        $this->ActionRepository = $ActionRepository;
        $this->route = $request->route();
        $this->request = $request;
    }
    
    /**
     * 菜单列表
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        $ret = $this->menuRepository->orderBy('id','desc')->paginate($this->perPage);
        $data = ['list' => $ret['data'],'page' => $ret['meta']['pagination']];
        return $this->success('ok',$data);
    }

    /**
     * 增加菜单
     *
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        $this->validate($request,[
            'name'        => 'required',
            'parent_id'   => 'required',
            'description' => 'required',
        ],[
            'name.required'        => '菜单名称不能为空',
            'parent_id.required'   => '父级分类不能为空',
            'description.required' => '菜单描述不能为空',
        ]);
        DB::beginTransaction();
        try {
            // 存储完毕得到 menu_id
            $data_add=$request->all();
            if(empty($data_add['route'])){
                $data_add['route']='#';
            }
            if ($menu = $this->menuRepository->create($data_add)) {

                $data=$request->all();
                if(empty($data['route'])){
                    $group   ='parent_'.$menu['data']['menu_id'] ;
                    $name = $group.'.index';
                }else{
                    $explode = explode('/', $data['route']);
                    $array_filter   = array_filter($explode);
                    $group   = end($array_filter);
                    $name = $group.'.index';
                }


                //如果接口路径写了 并且不是顶级菜单
                if(!empty($data['apiroute']) && $data['parent_id']!=0){
                    $getSave = $this->handleActions($menu['data']['menu_id']);
                    $act_menu_id = $this->ActionRepository->multiSave($getSave);

                    //添加permission--action
                    $act_per=[];
                    foreach($act_menu_id as $k=>$v){
                        $explode = explode('@', $v['action']);
                        $array_filter   = array_filter($explode);
                        $action   = end($array_filter);
                        $action_name = $group.'.'.$action;

                        $add_per=$this->ActionRepository->add_actionPermission($action_name,$v['name'],$v['description']);
                        $add_per['action_id']=$v['action_id'];
                        $add_per['menu_id']=$menu['data']['menu_id'];
                        $act_per[]=$add_per;
                    }
                    foreach($act_per as $k=>$v){
                        $data_act=[
                            'permission_id'=>$v['permission_id'],
                            'menu_id'=>$v['menu_id'],
                            'action_id'=>$v['action_id'],
                        ];
                        ActionPermission::query()->create($data_act);
                    }
                }

                //添加permission--menu
                $menu_per=$this->ActionRepository->add_menuPermission($name,$data['name'],$data['description']);
                $data_menu=[
                    'permission_id'=>$menu_per['permission_id'],
                    'menu_id'=>$menu['data']['menu_id'],
                ];
                MenuPermission::query()->create($data_menu);
                DB::commit();
                return $this->success('创建菜单成功',$data);

            }
        }
        catch (\Exception $e) {
            DB::rollback(); //事务回滚;
            $this->log('ERROR= = =1>'.var_export($e->getMessage(),1),'ERROR');
            return $this->error($e->getMessage());
        }
    }

    /**
     *  菜单详情
     *
     * @param  int $id
     *
     * @return \Illuminate\Http\Response
     */
    public function show($id)
    {
        $ret = $this->menuRepository->with(['actions'])->find($id);
        if (isset($ret['data']['actions']) && count($ret['data']['actions'])>0) {
            $ret['data']['preAction'] = $this->preAction($ret['data']['actions']);
        }
        return $this->success('ok', $ret['data']);
    }


    /**
     * 修改菜单
     * @param  int                                    $id
     *
     * @return \Illuminate\Http\Response
     */
    public function update(Request $request,$id)
    {
        $this->validate($request,[
            'name'        => 'required',
            'parent_id'   => 'required',
            'description' => 'required',
        ],[
            'name.required'        => '菜单名称不能为空',
            'parent_id.required'   => '父级分类不能为空',
            'description.required' => '菜单描述不能为空',
        ]);
        DB::beginTransaction();
//
        try {
            if ($menu = $this->menuRepository->update($request->all(),$id)) {

                $data = $this->request->all();
                $explode = explode('/', $data['route']);
                $array_filter   = array_filter($explode);
                $group   = end($array_filter);
                $name = $group.'.index';
                $arr = [
                    'name'=>$name,
                    'display_name'=>$data['name'],
                    'description'=>$data['description'],
                ];
                //更新 permission --- menu
                $menu_per=MenuPermission::query()->where('menu_id',$menu['data']['menu_id'])->get()->toArray();
//
                if(isset($menu_per[0]['permission_id'])){ // 关联表 menu_permission 有数据
                    $permission_id=$menu_per[0]['permission_id'];

                    $this->permissionRepository->updateOrCreate(['id'=>$permission_id],$arr);
                }else{// 关联表 menu_permission 无数据，先创建 permission 表数据
                    //添加 permission 获取 permission_id
                    $menu_per  = $this->ActionRepository->add_menuPermission($name,$data['name'],$data['description']);
                    $data_menu = [
                        'permission_id'=>$menu_per['permission_id'],
                        'menu_id'=>$menu['data']['menu_id'],
                    ];
                    // 创建关联表 menu_permission 信息
                    MenuPermission::query()->create($data_menu);
                    $permission_id = $menu_per['permission_id'];
                }

                //更新 permission --- action
                $act_arr=Action::query()->where('menu_id',$menu['data']['menu_id'])->get(['id'])->toArray();

                $act_id_arr=[];
                foreach($act_arr as $k=>$v){
                    $act_id_arr[]=$v['id'];
                }

                $role_id=[];
                $del_id=[];
                if($this->request->all('role')){
                    $actions=$this->handleActions($menu['data']['menu_id']);
                    foreach($actions as $k=>$v){
                        $arr=[
                            'menu_id'=>$v['menu_id'],
                            'group'=>$v['group'],
                            'action'=>$v['action'],
                            'name'=>$v['name'],
                            'description'=>$v['description'],
                        ];
                        if(!empty($v['id'])){//修改action
                            $role_id[]=$v['id'];
                            Action::query()->where('id',$v['id'])->update($arr);
                        }else{//新增action
                            $act_id=Action::query()->create($arr)->toArray();
                            $explode = explode('@', $act_id['action']);
                            $array_filter   = array_filter($explode);
                            $action   = end($array_filter);
                            $action_name = $group.'.'.$action;
                            $act_per=$this->ActionRepository->add_actionPermission($action_name,$act_id['name'],$act_id['description']);

                            $data_act=[
                                'permission_id'=>$act_per['permission_id'],
                                'action_id'=>$act_id['id'],
                            ];
                            ActionPermission::query()->create($data_act);
                        }
                    }

                    $del_id=array_diff($act_id_arr,$role_id);
                }
                if(!empty($del_id)){

                    foreach($del_id as $k=>$v){
                        $act_per_ret=ActionPermission::query()->where('action_id',$v)->get()->toArray();
                        if (isset($act_per_ret[0]['permission_id'])) {
                            $tempDelId = $act_per_ret[0]['permission_id'];
                            Permission::query()->where('id', $tempDelId)->delete();
                            Action::query()->where('id', $v)->delete();
                        }
                    }
                }
                DB::commit();
                return $this->success("编辑菜单成功",$permission_id);
            }
        }
        catch (\Exception $e) {
            DB::rollback(); //事务回滚;
            $this->log('ERROR= = =>UPDATE'.var_export($e->getMessage(),1),'ERROR-CUI');
            return $this->error($e->getMessage());
        }
    }

    /**
     * 删除菜单
     *
     * @param  int $id
     *
     * @return \Illuminate\Http\Response
     */
    public function destroy($id)
    {

        try {
            $act_per=[];
            $act=Action::query()->where("menu_id",$id)->get()->toArray();
            if(count($act)>0){
                foreach($act as $k=>$v){
                    $act_per_arr=ActionPermission::query()->where("action_id",$v['id'])->get()->toArray();
                    $act_per[]=isset($act_per_arr[0])?$act_per_arr[0]:[];
                }
            }
            $menu_per=MenuPermission::query()->where("menu_id",$id)->get()->toArray();
            if ($this->menuRepository->delete($id)) {
                if(!empty($act_per)){
                    foreach($act_per as $k=>$v){
                        Permission::query()->where("id",$v['permission_id'])->delete();
                    }
                }
                foreach($menu_per as $k=>$v){
                    Permission::query()->where("id",$v['permission_id'])->delete();
                }
                Action::query()->where('menu_id',$id)->delete();
                return $this->success("删除菜单成功");
            }
        }
        catch (\Exception $e) {
            return $this->error($e->getMessage());
        }
    }

    /**
     * 处理存储到 actions 表的数据
     *
     * @param  int $menu_id
     *
     * @return array
     */
    public function handleActions($menu_id){
        // 接口对应的路径
        $Current = 'App\Http\Controllers\Backend\\';
        $data    = $this->request->all();

        $explode = explode('/', $data['route']);

        $array_filter   = array_filter($explode);
        $group   = end($array_filter);

        $controller = $Current.$data['apiroute'].'@';
        // 定义存储空数组
        $saveArray = array();
        // 拼接 控制器字符串
        // 选择了增删改查 及 填入了其他选项
        if (isset($data['role']) && count($data['role'])>0) {
            foreach ($data['role'] as $key => $value) {
                $saveArray[$key]['menu_id']= $menu_id;
                $saveArray[$key]['group']  = $group;

                if (isset($value['id'])) {
                    $saveArray[$key]['id']  = $value['id'];
                }

                if (in_array($key,array('store','destroy','update','show'),true)) {
                    $saveArray[$key]['action'] = $controller.$key;
                    if (isset($value)&& $value !='on' ) {
                        $saveArray[$key]['id'] = $value;
                    }
                    switch ($key) {
                        case 'store':
                            $saveArray[$key]['name']        = '添加'.$data['name'];
                            $saveArray[$key]['description'] = '添加'.$data['name'];
                            break;

                        case 'update':
                            $saveArray[$key]['name']        = '修改'.$data['name'];
                            $saveArray[$key]['description'] = '修改'.$data['name'];
                            break;

                        case 'destroy':
                            $saveArray[$key]['name']        = '删除'.$data['name'];
                            $saveArray[$key]['description'] = '删除'.$data['name'];
                            break;

                        case 'show':
                            $saveArray[$key]['name']        = '查询'.$data['name'];
                            $saveArray[$key]['description'] = '查询'.$data['name'];
                            break;
                        // default:$this->log('default','ecclub');
                    }
                }else{
                    $saveArray[$key]['action'] = $controller.$value['action'];
                    $saveArray[$key]['name']        = $value['name'];
                    $saveArray[$key]['description'] = $value['description'];
                }
                continue;
            }
        }
        // $this->log('saveArray'.var_export($saveArray,1),'ecclub');
        return array_values($saveArray);
    }

    /**
     * 处理 actions 表编辑时展现的数据
     *
     * @param  array $actions
     *
     * @return array $actions
     */

    public function preAction($actions)
    {
        if (isset($actions)&&is_array($actions)) {
            $return = array();
            foreach ($actions as $key => $value) {
                $tempAction = explode('@', $value['action']);
                if (!isset($tempAction[1])) continue;
                if (in_array($tempAction[1],array('store','destroy','update','show'))) {
                    $return['operate'][$tempAction[1]]['flag'] = true;
                    $return['operate'][$tempAction[1]]['id'] = $value['id'];
                }else{
                    $return['elseAction'][$key]['action'] = $tempAction[1];
                    $return['elseAction'][$key]['name'] = $value['name'];
                    $return['elseAction'][$key]['description'] = $value['description'];
                    $return['elseAction'][$key]['id'] = $value['id'];
                }
            }
            if (isset($return['elseAction'])&&count($return['elseAction'])>0) {
                $return['elseAction'] = array_values($return['elseAction']);
            }
            return $return;
        }else{
            return false;
        }
    }

    /**
     * 处理 menu 表 对应存储的 permission 数据
     * 存储单条数据
     * @param  array $request
     *
     * @return array $actions
     */
    public function handleSaveMPermission($menu_id)
    {
        try {

            $data = $this->request->all();

            $explode = explode('/', $data['route']);
            $array_filter   = array_filter($explode);
            $group   = end($array_filter);
            $name = $group.'.index';
            // $menu_permission = MenuPermission::where('menu_id',53)->first()->toArray();
            $arr = [
                'name'=>$name,
                'display_name'=>$data['name'],
                'description'=>$data['description'],
                'type'=>'menu'
            ];
            // 存储到 permission 表
            $permission  = Permission::query()->updateOrCreate(['name'=>$name],$arr)->toArray();
            // $permission  = $this->menuRepository->add_menuPermission($name,$data['name'],$data['description']);

            // 根据 menu_id permission_id 存储到 menu_permission
            $saveArr  = [
                'menu_id'=>intval($menu_id),
                'permission_id'=>$permission['permission_id'],
            ];
            // 去掉原有数据，id 不会更改。
            \DB::table('menu_permission')->where('menu_id', '=', $menu_id)->delete();
            $saveMPer = MenuPermission::query()->updateOrCreate(['menu_id'=>$menu_id],$saveArr)->toArray();

        } catch (\Exception $e) {
            $this->log('ERROR= = =>2'.var_export($e->getMessage(),1),'ERROR');
            return false;
        }
        return true;
    }
    /**
     * 处理 actions 表 对应存储的 permission 数据
     *
     * @param  array $request
     *
     * @return array $actions
     */
    public function handleSaveAPermission($params,$menu_id)
    {
        try {
            if (is_array($params)) {
                // 查询出 action_permission 里的 permission_id ，删除 permission 表里的。循环里会添加上。
                // $ids = ActionPermission::where('menu_id',$menu_id)->get()->toArray();
                if (isset($params['temp'])) {
                    $ids = array_column($params['temp'],'permission_id') ;

                    unset($params['temp']);
                }

                $delete = Permission::whereIn('id',$ids)->delete();
                // 处理数据
                foreach ($params as $key => $value) {
                    $name = explode('@',$value['action']);
                    $name = $value['group'].'.'.$name[1];
                    $arr = [
                        'name'=>$name,
                        'display_name'=>$value['name'],
                        'description'=>$value['description'],
                        'type'=>'action'
                    ];
                    // 存储到 permission 表
                    $permission  = Permission::query()->updateOrCreate(['name'=>$name],$arr)->toArray();
                    // $permission  = $this->ActionRepository->add_actionPermission($name,$value['name'],$value['description']);

                    // 根据 action_id permission_id 存储到 action_permission
                    $saveArr  = [
                        'action_id'=>$value['id'],
                        'menu_id'=>$menu_id,
                        'permission_id'=>$permission['permission_id'],
                    ];
                    // ActionPermission::query()->where('action_id')->delete();
                    $ss = ActionPermission::query()->updateOrCreate(['action_id'=>$value['id']],$saveArr)->toArray();
                }
            }
        } catch (\Exception $e) {
            $this->log('ERROR= = =>3'.var_export($e->getMessage(),1),'ERROR');
            return false;
        }
        return true;
    }

    public function log($data,$filename){
        if(empty($filename)){
            $log_filename=$_SERVER['DOCUMENT_ROOT'].'/ecclub.php';
        }
        else{
            $log_filename=$_SERVER['DOCUMENT_ROOT'].'/'.$filename.'.php';
        }
        // 如果文件夹不存在则创建文件夹
        is_dir(dirname($log_filename)) || mkdir(dirname($log_filename),0777,true);
        // 日志大小
        $max_size=10485760;
        // 判断文件大小做自动删除动作
        if(file_exists($log_filename) && abs(filesize($log_filename))>$max_size){
            // 删除文件
            unlink($log_filename);
        }else{
            // 写日志(第三个参数是系统函数，可以连续写文件不覆盖)
            file_put_contents($log_filename, date("Y-m-d H:i:s",time()+8*60*60)." ".$data."\n", FILE_APPEND);
        }
    }

    /**
     * 菜单列表
     *
     * @return \Illuminate\Http\Response1
     */
    public function menu_all()
    {
        $ret = $this->menuRepository->with('menuAction')->scopeQuery(function($query){
            return $query;
        })->orderBy('parent_id','asc')->all();

        $data = $ret['data'];
        return $this->success('ok',$data);
    }

    /**
    * 操作权限
    */
    public function menu_per(Request $request){

       $data=$request->all();

       $this->requ_data=$data['menu'];
       $ret = $this->menuRepository->with(['menuPermission'])->scopeQuery(function($query){
           return $query->whereIn('id',$this->requ_data);
       })->orderBy('id','desc')->all();

        $cc=[];
       foreach($ret['data'] as $k =>$v){
           if(!empty($v['menu_permission'])){
               $roledata=[
                  'permission_id'=>$v['menu_permission']['permission_id'],
                  'role_id'=>$data['role_id']
              ];
              $cc[]=PermissionRole::query()->create($roledata);
           }

       }

       return $this->success('ok',$ret['data']);
    }
    public function checkRoute(){
        $data = $this->request->all();
        try {
            if (isset($data['route']) && $data['route']) {
                $getInfo = Permission::query()->where('name',$data['route'].'.index')->get()->toArray();
                if (count($getInfo)>0){
                    return $this->error('检测失败');
                }
                return $this->success('ok', ['data' => $getInfo]);
            }
        }catch (\Exception $e){
            return $this->error($e->getMessage());
        }
        return $this->error('检测失败');
    }


}
